import math
from ast import In
from multiprocessing.context import SpawnContext
from tkinter import BOTTOM, CENTER
from turtle import right
from this import d
from pyted import *
from algo.euler.autolayout_euler import autolayout_euler  # as autolayout
from algo.router import route

# from pyted.algo.router import route
# from pyted.modules import CurrentMirror
from modules.cm import CurrentMirror

# from pyted.modules.cm import CurrentMirror
from tedhub.common.opamp.src.opamp_generator import OpampGenerator


from pyted.kernel import *

# from pyted.modules.components import MomCap, PairedMosfet, Rpoly
from pyted.modules import VCVS, C, Capacitor, I, Mosfet, R, V, X
from pyted.modules import (
    NMOS,
    PMOS,
    MomCap,
    MosGrid,
    PairedMosfet,
    RpolySingle,
)
from pyted.utils import *

# from wyf.mylib.test_FullydifferialAmp import ful_dif_amp
from .HighPerformance_FDA import ful_dif_amp
from modules.components.mos.abba import *


class HP_FullyDifferentialAmp(OpampGenerator):
    def __init__(self, specs):
        super().__init__()
        self.pdk = os.environ.get("PDK") or "t65"
        self.circuit = ful_dif_amp(
            vdd = specs["VDD"], 
            vcm = specs["VCM"], 
            Cload = specs["CLoad"], 
            Iref = specs["Iref"],
            gain = specs["GAIN"],
            GBW = specs["GBW"],
            SR = specs["SR"],
            noise = specs["NOISE"],
        )
        
               
        self.vdd = self.circuit.vdd
        self.vcm = self.circuit.vcm_1st

    # @module
    def core(
        self,
        VINP: Input,
        VINN: Input,
        Iin: Input,
        CMFB1: Input,
        CMFB2: Input,
        VOP: Output,
        VON: Output,
        OP2: Output,
        ON2: Output,
        # OP2in: Output,
        # ON2in: Output,
        VCMO1: Output,
        GBN_inl: Output,
        GBN_inr: Output,
        GBN_outr: Output,
        GBN_outl: Output,
        GBP_inl: Output,
        GBP_inr: Output,
        GBP_outr: Output,
        GBP_outl: Output,
        Vout_CM: Output,
    ):
        """
        core函数描述模块的核心结构, 不包括外部的偏置电压及偏置电流等信息
        """

        self.circuit.show()
        IB200U1, IB200U2=Node(2)

        cmn = CurrentMirror(
            type="type5",
            model="nch",
            l=self.circuit.Nbias[1][0:2],
            w=self.circuit.Nbias[0][0:2],
            m=self.circuit.Nbias[2][0:2],
            place_mode="euler",
        )
        cmp = CurrentMirror(
            type="type5",
            model="pch",
            l=self.circuit.Pbias[1][0:2],
            w=self.circuit.Pbias[0][0:2],
            m=self.circuit.Pbias[2][0:2],
            place_mode="euler",
        )
        cmn_bias = CurrentMirror(
            type="type1",
            model="nch",
            l=self.circuit.Nbias[1][2:4],
            w=self.circuit.Nbias[0][2:4],
            m=self.circuit.Nbias[2][2:4],
            place_mode="euler",
        )
        cmp_bias = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][2:4],
            w=self.circuit.Pbias[0][2:4],
            m=self.circuit.Pbias[2][2:4],
            place_mode="euler",
        )

        """偏置电路"""
        PB1, PB2, PB3, COM2, COM1 = Node(5)
        # GBN_inr, GBN_inl, GBP_inl, GBP_inr =Node(4)
        cmn_bias.input(IB200U1, type1_Transform=1)
        cmn.input(Idc=IB200U2, VB=IB200U1)
        cmn.output(PB1, k=1)  # 为Pbias偏置
        cmn.output(PB2, k=1, single=False)  # 该点原为单管输出，双管所需电压较大，若电压不足可改为single=true
        cmn.output(PB3, k=1)

        
        Iin_cmp = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        Iin_cmp.input(Idc=Iin)
        Iin_cmp.output(IB200U2, k=1)  # 该点原为单管输出，双管所需电压较大，若电压不足可改为single=true
        Iin_cmp.output(IB200U1, k=1)

        Cmnf = NMOS_ABBA_CO_VSS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.firstStageAmp[3][0] / 2*2),
        )
        (GBN_inl, GBN_inr) >> Cmnf % (IB200U2, IB200U2)

        cmn2nd = CurrentMirror(
            type="type1",
            model="nch",
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=self.circuit.Nbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Nbias[1][1],
        )
        cmn2nd.outputs = [IB200U2]
        cmn2nd.output(
            COM2,
            k=self.circuit.secondStageAmp[3] / self.circuit.bias_multi,
            single=True,
        )  # 二级运放负载
        Cmn2nd = cmn2nd.row()

        cmp.input(Idc=PB1, VB=PB2)
        cmp_bias.input(Idc=PB2, type1_Transform=1)

        cmp1tr = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        cmp1tr.outputs = [PB1]
        cmp1tr.output(
            COM1,
            k=self.circuit.firstStageAmp[3][0] / self.circuit.bias_multi,
            single=True,
        )  # 输入级尾电流
        Cmp1tr = cmp1tr.row()

        cmp1tl = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        cmp1tl.outputs = [PB1]
        cmp1tl.output(
            COM1,
            k=self.circuit.firstStageAmp[3][0] / self.circuit.bias_multi,
            single=True,
        )  # 输入级尾电流
        Cmp1tl = cmp1tl.row()

        Cmp1 = PMOS_ABBA_CO_VDD(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(
                self.circuit.Pbias[2][1]
                * self.circuit.firstStageAmp[4][0]
                / self.circuit.bias_multi
                / 2*2
            ),
        )
        (GBP_inl, GBP_inr) >> Cmp1 % (PB1, PB1)

        cmp2 = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        cmp2.input(Idc=PB3)


        A2_load = PMOS_ABBA_CO_VDD(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(
                self.circuit.Pbias[2][1]
                * self.circuit.secondStageAmp[3]
                / self.circuit.bias_multi
                / 2
            ),
        )
        (VON, VOP) >> A2_load % (PB3, PB3)

        """N型Gaiboostor"""
        # GBN_outl, GBN_outr, GBP_outr, GBP_outl = Node(4)
        (
            mid1,
            mid2,
            mid3,
            mid4,
            mid5,
            mid6,
            mid7,
            mid8,
        ) = Node(8)

        """以常规方式描述"""
        #GBNl
        GBNlin_cas_cm1 = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi),
        )
        GBN_inl >> GBNlin_cas_cm1 % IB200U2 >> Vss()
        GBNlin_cas_cm2 = NMOS(
            l=self.circuit.Nbias[1][0],
            w=self.circuit.Nbias[0][0],
            m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi),
        )
        mid1 >> GBNlin_cas_cm2 % IB200U1 >> GBN_inl
        GBNlin_cm = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        )
        mid1 >> GBNlin_cm % mid1 >> Vdd()

        GBNlout_cas_cm1 = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi),
        )
        mid2 >> GBNlout_cas_cm1 % IB200U2 >> Vss()
        GBNlout_cas_cm2 = NMOS(
            l=self.circuit.Nbias[1][0],
            w=self.circuit.Nbias[0][0],
            m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi),
        )
        GBN_outl >> GBNlout_cas_cm2 % IB200U1 >> mid2
        GBNlout_cm = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        )
        GBN_outl >> GBNlout_cm % mid1 >> Vdd()
        GBNl_cas_cm1 = layout_mos(mosfets=[GBNlin_cas_cm1, GBNlout_cas_cm1,], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][0], outer_dummy_m=1)
        GBNl_cas_cm2 = layout_mos(mosfets=[GBNlin_cas_cm2, GBNlout_cas_cm2,], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][0], outer_dummy_m=1)
        GBNl_cm = layout_mos(mosfets=[GBNlin_cm ,GBNlout_cm], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][1], outer_dummy_m=1)
        GBNl = col(
            guardring(GBNl_cm, connectTo=Vdd()),
            guardring(col(GBNl_cas_cm2, GBNl_cas_cm1,align=RIGHT), connectTo=Vss()),
            align=RIGHT
        )



        #GBNr
        GBNrin_cas_cm1 = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi),
        )
        GBN_inr >> GBNrin_cas_cm1 % IB200U2 >> Vss()
        GBNrin_cas_cm2 = NMOS(
            l=self.circuit.Nbias[1][0],
            w=self.circuit.Nbias[0][0],
            m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi),
        )
        mid3 >> GBNrin_cas_cm2 % IB200U1 >> GBN_inr
        GBNrin_cm = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        )
        mid3 >> GBNrin_cm % mid3 >> Vdd()

        GBNrout_cas_cm1 = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi),
        )
        mid4 >> GBNrout_cas_cm1 % IB200U2 >> Vss()
        GBNrout_cas_cm2 = NMOS(
            l=self.circuit.Nbias[1][0],
            w=self.circuit.Nbias[0][0],
            m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi),
        )
        GBN_outr >> GBNrout_cas_cm2 % IB200U1 >> mid4
        GBNrout_cm = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        )
        GBN_outr >> GBNrout_cm % mid3 >> Vdd()
        GBNr_cas_cm1 = layout_mos(mosfets=[GBNrout_cas_cm1, GBNrin_cas_cm1], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][0], outer_dummy_m=1)
        GBNr_cas_cm2 = layout_mos(mosfets=[GBNrout_cas_cm2, GBNrin_cas_cm2], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][0], outer_dummy_m=1)
        GBNr_cm = layout_mos(mosfets=[GBNrout_cm, GBNrin_cm], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][1], outer_dummy_m=1)
        GBNr = col(
            guardring(GBNr_cm, connectTo=Vdd()),
            guardring(col(GBNr_cas_cm2, GBNr_cas_cm1,align=LEFT), connectTo=Vss()),
            align=LEFT
        )

        


        """以常规电流镜形式布局"""
        # GBNl_cas_cm = CurrentMirror(type="type5", model = "nch", l= self.circuit.Nbias[1][0:2], w= self.circuit.Nbias[0][0:2], m= self.circuit.Nbias[2][0:2], place_mode="euler", l_dummy=self.circuit.Nbias[1][1],)
        # GBNl_cas_cm.outputs = [IB200U1, IB200U2]
        # GBNl_cas_cm.output(mid1, mid=GBN_inl, k=self.circuit.NGB_multi)
        # GBNl_cas_cm.output(GBN_outl, k=self.circuit.NGB_multi)

        # GBNl_cm = CurrentMirror(
        #     type="type1",
        #     model="pch",
        #     l=self.circuit.Pbias[1][1],
        #     w=self.circuit.Pbias[0][1],
        #     m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        #     place_mode="euler",
        #     l_dummy=self.circuit.Pbias[1][1],
        # )
        # GBNl_cm.input(Idc=mid1)
        # GBNl_cm.output(Iout=GBN_outl, k=1)
        # LGBNl_cas_cm = GBNl_cas_cm.col()
        # LGBNl_cm = GBNl_cm.row(align=TOP)
        # GBNl = col(
        #     guardring(LGBNl_cm, connectTo=Vdd()),
        #     guardring(LGBNl_cas_cm, connectTo=Vss()),
        #     align=CENTER
        # )

        # # cmp.output(mid1, k=1/2, single=True)
        # # cmp.output(GBN_outl, k=1/2, single=True)

        # # cmn.output(mid3, mid=GBN_inr, k=self.circuit.NGB_multi)
        # # cmn.output(GBN_outr, k=self.circuit.NGB_multi)
        # GBNr_cas_cm = CurrentMirror(type="type5", model = "nch", l= self.circuit.Nbias[1][0:2], w= self.circuit.Nbias[0][0:2], m= self.circuit.Nbias[2][0:2], place_mode="euler", l_dummy=self.circuit.Nbias[1][1],)
        # GBNr_cas_cm.outputs = [IB200U1, IB200U2]
        # GBNr_cas_cm.output(mid3, mid=GBN_inr, k=self.circuit.NGB_multi)
        # GBNr_cas_cm.output(GBN_outr, k=self.circuit.NGB_multi)
        # GBNr_cm = CurrentMirror(
        #     type="type1",
        #     model="pch",
        #     l=self.circuit.Pbias[1][1],
        #     w=self.circuit.Pbias[0][1],
        #     m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi),
        #     place_mode="euler",
        #     l_dummy=self.circuit.Pbias[1][1],
        # )
        # GBNr_cm.input(Idc=mid3)
        # GBNr_cm.output(Iout=GBN_outr, k=1)
        # # cmp.output(mid3, k=1/2, single=True)
        # # cmp.output(GBN_outr, k=1/2, single=True)
        # LGBNr_cas_cm = GBNr_cas_cm.col()
        # LGBNr_cm = GBNr_cm.row(align=TOP)
        # GBNr = col(            
        #     guardring(LGBNr_cm.flipy(), connectTo=Vdd()),
        #     guardring(LGBNr_cas_cm.flipy(), connectTo=Vss()),
        #     align=CENTER
        # )

        # # LGBN = row(
        # #     guardring(
        # #         col(LGBNl_cm, LGBNr_cm.flipx(), spacing=600, align=CENTER),
        # #         connectTo=Vdd()
        # #     ),
        # #     guardring(
        # #         col(LGBNl_cas_cm.flipx(), LGBNr_cas_cm, spacing=600, align=CENTER),
        # #         connectTo=Vss()
        # #     ),
        # #     align=MIDDLE
        # # ).add_vbus(
        # #     GBN_inl, GBN_inr, GBN_outr, GBN_outr, layer=M3, vias=2, location=LEFT
        # # )


        """GBN以ABBA方式布局"""
        # GBNin_cas_cm1 = NMOS_ABBA_CO_VSS(
        #     l=self.circuit.Nbias[1][1],
        #     w=self.circuit.Nbias[0][1],
        #     m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi / 2),
        # )
        # (GBN_inl, GBN_inr) >> GBNin_cas_cm1 % (IB200U2, IB200U2)
        # debug(int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi / 2),int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi / 2))
        # GBNin_cas_cm2 = ABBA(
        #     l=self.circuit.Nbias[1][0],
        #     w=self.circuit.Nbias[0][0],
        #     m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi / 2),
        #     model="nch",
        # )
        # (mid1, mid3) >> GBNin_cas_cm2 % (IB200U1, IB200U1) >> (GBN_inl, GBN_inr)
        
        # GBNin_cm = PMOS_ABBA_CO_VDD(
        #     l=self.circuit.Pbias[1][1],
        #     w=self.circuit.Pbias[0][1],
        #     m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi / 2),
        # )
        # (mid1, mid3) >> GBNin_cm % (mid1, mid3)

        # GBNout_cas_cm1 = NMOS_ABBA_CO_VSS(
        #     l=self.circuit.Nbias[1][1],
        #     w=self.circuit.Nbias[0][1],
        #     m=int(self.circuit.Nbias[2][1] * self.circuit.NGB_multi / 2),
        # )
        # (mid2, mid4) >> GBNout_cas_cm1 % (IB200U2, IB200U2)
        # GBNout_cas_cm2 = ABBA(
        #     l=self.circuit.Nbias[1][0],
        #     w=self.circuit.Nbias[0][0],
        #     m=int(self.circuit.Nbias[2][0] * self.circuit.NGB_multi / 2),
        #     model="nch",
        # )
        # (GBN_outl, GBN_outr) >> GBNout_cas_cm2 % (IB200U1, IB200U1) >> (mid2, mid4)
        # GBNout_cm = PMOS_ABBA_CO_VDD(
        #     l=self.circuit.Pbias[1][1],
        #     w=self.circuit.Pbias[0][1],
        #     m=int(2 * self.circuit.Pbias[2][1] * self.circuit.NGB_multi / 2),
        # )
        # (GBN_outl, GBN_outr) >> GBNout_cm % (mid1, mid3)
        # LGBN = col(
        #     guardring(col(GBNin_cm, GBNout_cm), connectTo=Vdd()),
        #     guardring(
        #         col(
        #             GBNin_cas_cm2, GBNout_cas_cm2,
        #             GBNin_cas_cm1, GBNout_cas_cm1,
        #             align=CENTER,
        #         ),
        #         connectTo=Vss(),
        #     ),
        #     align=CENTER,
        # )

        """P型gainboostor"""

        """以常规方式描述"""
        #GBPl
        GBPlin_cas_cm1 = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(self.circuit.Pbias[2][1] * self.circuit.PGB_multi),
        )
        GBP_inl >> GBPlin_cas_cm1 % PB1 >> Vdd()
        GBPlin_cas_cm2 = PMOS(
            l=self.circuit.Pbias[1][0],
            w=self.circuit.Pbias[0][0],
            m=int(self.circuit.Pbias[2][0] * self.circuit.PGB_multi),
        )
        mid5 >> GBPlin_cas_cm2 % PB2 >> GBP_inl
        GBPlin_cm = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(2 * self.circuit.Nbias[2][1] * self.circuit.PGB_multi),
        )
        mid5 >> GBPlin_cm % mid5 >> Vss()

        GBPlout_cas_cm1 = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(self.circuit.Pbias[2][1] * self.circuit.PGB_multi),
        )
        mid6 >> GBPlout_cas_cm1 % PB1 >> Vdd()
        GBPlout_cas_cm2 = PMOS(
            l=self.circuit.Pbias[1][0],
            w=self.circuit.Pbias[0][0],
            m=int(self.circuit.Pbias[2][0] * self.circuit.PGB_multi),
        )
        GBP_outl >> GBPlout_cas_cm2 % PB2 >> mid6
        GBPlout_cm = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(2 * self.circuit.Nbias[2][1] * self.circuit.PGB_multi),
        )
        GBP_outl >> GBPlout_cm % mid5 >> Vss()
        GBPl_cas_cm1 = layout_mos(mosfets=[GBPlin_cas_cm1, GBPlout_cas_cm1,], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][0], outer_dummy_m=1)
        GBPl_cas_cm2 = layout_mos(mosfets=[GBPlin_cas_cm2, GBPlout_cas_cm2,], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][0], outer_dummy_m=1)
        GBPl_cm = layout_mos(mosfets=[GBPlin_cm ,GBPlout_cm], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][1], outer_dummy_m=1)
        GBPl = col(
            guardring(col(GBPl_cas_cm1, GBPl_cas_cm2,align=CENTER), connectTo=Vdd()),
            guardring(GBPl_cm, connectTo=Vss()),
            align=CENTER
        )

        #GBPr
        GBPrin_cas_cm1 = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(self.circuit.Pbias[2][1] * self.circuit.PGB_multi),
        )
        GBP_inr >> GBPrin_cas_cm1 % PB1 >> Vdd()
        GBPrin_cas_cm2 = PMOS(
            l=self.circuit.Pbias[1][0],
            w=self.circuit.Pbias[0][0],
            m=int(self.circuit.Pbias[2][0] * self.circuit.PGB_multi),
        )
        mid7 >> GBPrin_cas_cm2 % PB2 >> GBP_inr
        GBPrin_cm = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(2 * self.circuit.Nbias[2][1] * self.circuit.PGB_multi),
        )
        mid7 >> GBPrin_cm % mid7 >> Vss()

        GBProut_cas_cm1 = PMOS(
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=int(self.circuit.Pbias[2][1] * self.circuit.PGB_multi),
        )
        mid8 >> GBProut_cas_cm1 % PB1 >> Vdd()
        GBProut_cas_cm2 = PMOS(
            l=self.circuit.Pbias[1][0],
            w=self.circuit.Pbias[0][0],
            m=int(self.circuit.Pbias[2][0] * self.circuit.PGB_multi),
        )
        GBP_outr >> GBProut_cas_cm2 % PB2 >> mid8
        GBProut_cm = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(2 * self.circuit.Nbias[2][1] * self.circuit.PGB_multi),
        )
        GBP_outr >> GBProut_cm % mid7 >> Vss()
        GBPr_cas_cm1 = layout_mos(mosfets=[GBProut_cas_cm1 ,GBPrin_cas_cm1], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][0], outer_dummy_m=1)
        GBPr_cas_cm2 = layout_mos(mosfets=[GBProut_cas_cm2 ,GBPrin_cas_cm2], connect_g_by_po=False, outer_dummy_l=self.circuit.Pbias[1][0], outer_dummy_m=1)
        GBPr_cm = layout_mos(mosfets=[GBProut_cm ,GBPrin_cm], connect_g_by_po=False, outer_dummy_l=self.circuit.Nbias[1][1], outer_dummy_m=1)
        GBPr = col(
            guardring(col(GBPr_cas_cm1, GBPr_cas_cm2,align=CENTER), connectTo=Vdd()),
            guardring(GBPr_cm, connectTo=Vss()),
            align=CENTER
        )

        

        """第一级运放"""
        # debug(self.circuit.firstStageAmp[1][0], self.circuit.firstStageAmp[0][0], self.circuit.firstStageAmp[2][0])
        inputpair = PairedMosfet(
            l=self.circuit.firstStageAmp[1][0],
            w=self.circuit.firstStageAmp[0][0],
            model="pch",
            m=self.circuit.firstStageAmp[2][0],
            mode="cross",
            dummy_m=1,
            dummy_l=self.circuit.firstStageAmp[1][0],
        )
        (GBN_inl, GBN_inr) >> inputpair % (VINN, VINP) >> COM1
        

        if self.circuit.firstStageAmp[2][1] == 1:
            nl = NMOS(
                l=self.circuit.firstStageAmp[1][1],
                w=self.circuit.firstStageAmp[0][1],
                m=self.circuit.firstStageAmp[2][1],
            )
            ON2 >> nl % GBN_outl>> GBN_inl
            nr = NMOS(
                l=self.circuit.firstStageAmp[1][1],
                w=self.circuit.firstStageAmp[0][1],
                m=self.circuit.firstStageAmp[2][1],
            )
            OP2 >> nr % GBN_outr >> GBN_inr
            mn = layout_mos(mosfets=[nl, nr], connect_g_by_po=False, outer_dummy_m=1)
            
            pl = PMOS(
                l=self.circuit.firstStageAmp[1][2],
                w=self.circuit.firstStageAmp[0][2],
                m=self.circuit.firstStageAmp[2][2],
            )
            ON2 >> pl % GBP_outl>> GBP_inl
            pr = PMOS(
                l=self.circuit.firstStageAmp[1][2],
                w=self.circuit.firstStageAmp[0][2],
                m=self.circuit.firstStageAmp[2][2],
            )
            OP2 >> pr % GBP_outr >> GBP_inr
            mp = layout_mos(mosfets=[pl, pr], connect_g_by_po=False, outer_dummy_m=1)
        else:
            mn = ABBA(
                l=self.circuit.firstStageAmp[1][1],
                w=self.circuit.firstStageAmp[0][1],
                m=int(self.circuit.firstStageAmp[2][1] / 2),
                model="nch",
            )
            (ON2, OP2) >> mn % (GBN_outl, GBN_outr) >> (GBN_inl, GBN_inr)
            mp = ABBA(
                l=self.circuit.firstStageAmp[1][2],
                w=self.circuit.firstStageAmp[0][2],
                m=int(self.circuit.firstStageAmp[2][2] / 2),
                model="pch",
            )
            (ON2, OP2) >> mp % (GBP_outl, GBP_outr) >> (GBP_inl, GBP_inr)

        """第二级运放"""
        
        # inputpair2 = PairedMosfet(
        #     l=self.circuit.secondStageAmp[1],
        #     w=self.circuit.secondStageAmp[0],
        #     model="nch",
        #     m=self.circuit.secondStageAmp[2],
        #     mode="cross",
        #     dummy_m=1,
        #     dummy_l=self.circuit.secondStageAmp[1],
        # )
        # (VON, VOP) >> inputpair2 % (ON2, OP2) >> COM2
        
        in2pairR = NMOS(
            l=self.circuit.secondStageAmp[1],
            w=self.circuit.secondStageAmp[0]*2,
            m=int(self.circuit.secondStageAmp[2]/2),
        )
        in2pairL = NMOS(
            l=self.circuit.secondStageAmp[1],
            w=self.circuit.secondStageAmp[0]*2,
            m=int(self.circuit.secondStageAmp[2]/2),
        )
        VON >> in2pairR % ON2 >> COM2
        VOP >> in2pairL % OP2 >> COM2
        inputpair2 = layout_mos(mosfets=[in2pairR, in2pairL], connect_g_by_po=False, outer_dummy_m=1)

        

        """共模电平"""
        VCMO2 = Node(1)
        cmp.output(VCMO1, k=self.circuit.CMFBO[3][0]/self.circuit.bias_multi)  # 共模输出电压
        cmp.output(VCMO2, k=self.circuit.CMFBO[3][0]/self.circuit.bias_multi)
        vcmo2 = NMOS(
            l=self.circuit.CMFBO[1][1],
            w=self.circuit.CMFBO[0][1],
            m=self.circuit.CMFBO[2][1],
        )
        VCMO2 >> vcmo2 % VCMO2 >> Vss()


        vcmo1 = NMOS(
            l=self.circuit.CMFBO[1][0],
            w=self.circuit.CMFBO[0][0],
            m=self.circuit.CMFBO[2][0],
        )
        VCMO1 >> vcmo1 % VCMO1 >> Vss()

        

        LVCMO1 = layout_mos(mosfets=[vcmo1], connect_g_by_po=False, outer_dummy_m=1)
        LVCMO2 = layout_mos(mosfets=[vcmo2], connect_g_by_po=False, outer_dummy_m=1)


        fb1 = NMOS_ABBA_CO_VSS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.firstStageAmp[4][0] / 2),
        )
        (GBN_inl, GBN_inr) >> fb1 % (CMFB1, CMFB1)

        fb2 = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=self.circuit.secondStageAmp[3],
        )
        COM2 >> fb2 % CMFB2 >> Vss()
        Lfb2 = layout_mos(mosfets=[fb2])


        """第一级CMFB"""
        itail1_1, itail1_2, CMFB1m = Node(3)
        CM1_cmp = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        CM1_cmp.outputs = [PB1]

        CM1_cmp.output(
            itail1_1,
            k=self.circuit.CMFB_1st[3] / self.circuit.bias_multi * 2,
            single=True,
        )
        CM1_cmp.output(
            itail1_2,
            k=self.circuit.CMFB_1st[3] / self.circuit.bias_multi * 2,
            single=True,
        )
        LCM1_cmp = CM1_cmp.row()
        
        # inputpair1l = PairedMosfet(
        #     l=self.circuit.CMFB_1st[1],
        #     w=round(self.circuit.CMFB_1st[0]*2, 8),
        #     model="pch",
        #     m=self.circuit.CMFB_1st[2],
        #     mode="cross",
        #     dummy_m=1,
        #     dummy_l=self.circuit.CMFB_1st[1],
        # )
        # (CMFB1m, CMFB1) >> inputpair1l % (OP2, VCMO1) >> itail1_1
        if self.pdk in ["t180"]:
            inputpair1ll = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*5,
                m=int(self.circuit.CMFB_1st[2]/4),
            )
            inputpair1lr = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*5,
                m=int(self.circuit.CMFB_1st[2]/2),
            )
        # if self.pdk in ["t65"]:
        #     inputpair1ll = PMOS(
        #         l=self.circuit.CMFB_1st[1],
        #         w=self.circuit.CMFB_1st[0]*7,
        #         m=int(self.circuit.CMFB_1st[2]/4),
        #     )
        #     inputpair1lr = PMOS(
        #         l=self.circuit.CMFB_1st[1],
        #         w=self.circuit.CMFB_1st[0]*7,
        #         m=int(self.circuit.CMFB_1st[2]/2),
        #     ) 
        else:
            inputpair1ll = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*3,
                m=int(self.circuit.CMFB_1st[2]/2),
            )
            inputpair1lr = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*3,
                m=int(self.circuit.CMFB_1st[2]/2),
            )
        CMFB1m >> inputpair1ll % OP2 >> itail1_1
        CMFB1 >> inputpair1lr % VCMO1 >> itail1_1
        inputpair1l = layout_mos(mosfets=[inputpair1ll, inputpair1lr], connect_g_by_po=False, outer_dummy_m=1)
        
        
        # inputpair1r = PairedMosfet(
        #     l=self.circuit.CMFB_1st[1],
        #     w=round(self.circuit.CMFB_1st[0]*2, 8),
        #     model="pch",
        #     m=self.circuit.CMFB_1st[2],
        #     mode="cross",
        #     dummy_m=1,
        #     dummy_l=self.circuit.CMFB_1st[1],
        # )
        # (CMFB1m, CMFB1) >> inputpair1r % (ON2, VCMO1) >> itail1_2
        if self.pdk in ["t180"]:
            inputpair1rl = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*5,
                m=int(self.circuit.CMFB_1st[2]/4),
            )
            inputpair1rr = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*5,
                m=int(self.circuit.CMFB_1st[2]/4),
            )
        else:
            inputpair1rl = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*3,
                m=int(self.circuit.CMFB_1st[2]/2),
            )
            inputpair1rr = PMOS(
                l=self.circuit.CMFB_1st[1],
                w=self.circuit.CMFB_1st[0]*3,
                m=int(self.circuit.CMFB_1st[2]/2),
            )
        CMFB1m >> inputpair1rl % ON2 >> itail1_2
        CMFB1 >> inputpair1rr % VCMO1 >> itail1_2
        inputpair1r = layout_mos(mosfets=[inputpair1rl, inputpair1rr], connect_g_by_po=False, outer_dummy_m=1)
        

        # CM_fb = NMOS_ABBA_CO_VSS(
        #     l=self.circuit.Nbias[1][1],
        #     w=self.circuit.Nbias[0][1],
        #     m=self.circuit.CMFB_1st[3],
        # )
        # (CMFB1, CMFB1m) >> CM_fb % (CMFB1, CMFB1m)
        debug(self.circuit.Nbias[0][1])
        CM_fbl = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=self.circuit.CMFB_1st[3]*2,
        )
        CM_fbr = NMOS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=self.circuit.CMFB_1st[3]*2,
        )
        CMFB1 >> CM_fbl % CMFB1 >> Vss()
        CMFB1m >> CM_fbr % CMFB1m >> Vss()
        CM_fb = layout_mos(mosfets=[CM_fbl, CM_fbr], connect_g_by_po=False, outer_dummy_m=1)
        

        """电阻电容检测型"""
        itail2, CMFB2m = Node(2)
        

        CM2_cmr = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        CM2_cmr.outputs = [PB1]
        CM2_cmr.output(
            itail2,
            k=self.circuit.CMFB_2nd[3] / self.circuit.bias_multi,
            single=True,
        )
        LCM2_cmr = CM2_cmr.row()
        CM2_cml = CurrentMirror(
            type="type1",
            model="pch",
            l=self.circuit.Pbias[1][1],
            w=self.circuit.Pbias[0][1],
            m=self.circuit.Pbias[2][1],
            place_mode="euler",
            l_dummy=self.circuit.Pbias[1][1],
        )
        CM2_cml.outputs = [PB1]
        CM2_cml.output(
            itail2,
            k=self.circuit.CMFB_2nd[3] / self.circuit.bias_multi,
            single=True,
        )
        LCM2_cml = CM2_cml.row()
        debug("这里出了问题3")
        CM2inpair = PairedMosfet(
            l=self.circuit.CMFB_2nd[1],
            w=round(self.circuit.CMFB_2nd[0]*3, 8),
            model="pch",
            m=self.circuit.CMFB_2nd[2]*2,
            mode="cross",
            dummy_m=1,
            dummy_l=self.circuit.CMFB_2nd[1],
        )
        (CMFB2m, CMFB2) >> CM2inpair % (Vout_CM, VCMO2) >> itail2

        
        CM2_fb = NMOS_ABBA_CO_VSS(
            l=self.circuit.Nbias[1][1],
            w=self.circuit.Nbias[0][1],
            m=int(self.circuit.CMFB_2nd[3] / 2),
        )
        (CMFB2, CMFB2m) >> CM2_fb % (CMFB2, CMFB2m)
    


        """layout"""
        
        Cmn = cmn.row(align=BOTTOM).add_label("cmn")
        Cmp = cmp.row(align=BOTTOM).add_label("cmp")
        Cmp_Iin = Iin_cmp.row(align=BOTTOM)
        Cmn_bias = cmn_bias.row().add_label("cmn_bias")
        Cmp_bias = cmp_bias.row(align=TOP).add_label("cmp_bias")
        Cmp2 = cmp2.add_label("cmp2")

        LNbias = guardring(
            row(Cmn_bias, Cmn, row(Cmn2nd, Lfb2), align=MIDDLE), connectTo=Vss()
        )
        LPbias = guardring(
            row(Cmp_bias, Cmp_Iin,  Cmp, Cmp2, Cmp1tr, Cmp1tl, align=BOTTOM),
            connectTo=Vdd(),
        )
        LCMFB1 = col(
            guardring(
                LCM1_cmp,
                connectTo=Vdd(),
            ),
            guardring(
                row(inputpair1l, inputpair1r, spacing=600, align=MIDDLE),
                connectTo=Vdd(),
            ),
            guardring(CM_fb, connectTo=Vss()),
            align=CENTER
        )
        LCMFB2 = col(
            guardring(
                col(
                    row(LCM2_cmr, LCM2_cml, align=MIDDLE),
                    CM2inpair,
                    align=CENTER
                ),
                connectTo=Vdd(),
            ),
            guardring(CM2_fb, connectTo=Vss()),
            align=CENTER            
        )
        signal_M = col(
            guardring(Cmp1, connectTo=Vdd()),
            row(
                col(
                    GBPl,
                    GBNl,
                    align=RIGHT
                ),
                col(
                    guardring(inputpair2, connectTo=Vss()),
                    guardring(mp, connectTo=Vdd()),
                    guardring(inputpair, connectTo=Vdd()),
                    guardring(mn, connectTo=Vss()), 
                    align=CENTER                   
                ),
                col(
                    GBPr,
                    GBNr,
                    align=LEFT
                ),
                spacing=600,
                align=MIDDLE
            ),
            guardring(row(Cmnf, fb1, align=MIDDLE), connectTo=Vss()),
            align=CENTER
        )
        if self.pdk in ["t65"]:
            block1 = col(
                LPbias,
                guardring(A2_load, connectTo=Vdd()),   
                signal_M,   
                align=CENTER
            )
            final = col(
                row(
                    col(
                        guardring(row(LVCMO2, LVCMO1, align=MIDDLE), connectTo=Vss()),
                        LCMFB2, 
                        LCMFB1, 
                        align=CENTER
                    ),               
                    block1,
                    align=BOTTOM
                ),
                LNbias,
                align=CENTER
            )
        else:
            block1 = col(
                guardring(A2_load, connectTo=Vdd()),
                row(
                    col(
                        guardring(row(LVCMO2, LVCMO1, align=MIDDLE), connectTo=Vss()),
                        LCMFB2, 
                        LCMFB1, 
                        align=CENTER
                    ),
                    signal_M,
                    spacing=500,
                    align=MIDDLE
                ), 
                align=CENTER
            )
            final = col(
                LPbias,
                block1,
                LNbias,
                align=CENTER
            )


        place(final)
        route()
        current_module().expose_all_ports()

    # @module
    def wrapper(self, VINP, VINN, Non, vop: Output, von: Output):
        """
        wrapper函数描述模块的外围结构, 包括偏置电压或偏置电流。
        并且输入输出需要与Generator基类保持一致。
        """
        Iin, CMFB1, CMFB2 = Node(3)
        # von, vop, op2, on2, vcmo = ~self.core(VINP, VINN, IB200U1, IB200U2, CMFB1, CMFB2)
        op2, on2, vcmo = Node(3)
        Vout_CM = Node(1)
        (
            GBN_inl,
            GBN_inr,
            GBN_outr,
            GBN_outl,
            GBP_inl,
            GBP_inr,
            GBP_outr,
            GBP_outl,
        ) = Node(8)
        op2in, on2in =Node(2)
        dut = self.build(VINP, VINN, Iin, CMFB1, CMFB2)
        dut >> (
            vop,
            von,
            op2,
            on2,
            # op2in,
            # on2in,
            vcmo,
            GBN_inl,
            GBN_inr,
            GBN_outr,
            GBN_outl,
            GBP_inl,
            GBP_inr,
            GBP_outr,
            GBP_outl,
            Vout_CM,
        )
        (Vout_CM, von) >> R(r=100e3)
        (Vout_CM, von) >> C(c=0.5e-12)
        (Vout_CM, vop) >> R(r=100e3)
        (Vout_CM, vop) >> C(c=0.5e-12)
        # (vcmo, Vss()) >> V(dc=0.9) 
        # (Vout_CM, von) >> R(r=50e3)
        # (Vout_CM, von) >> C(c=0.5e-12)
        # (Vout_CM, vop) >> R(r=50e3)
        # (Vout_CM, vop) >> C(c=0.5e-12)

        # I(Vdd(), IB200U1, dc=self.circuit.Iref)
        I(Iin, Vss(), dc=self.circuit.Iref)
        C(von, Vss(), c=3e-12)
        C(vop, Vss(), c=3e-12)

        """
        hybrid cascode compensation
        """
        debug(self.circuit.Cc_cascode, self.circuit.GBN_Cc, self.circuit.GBP_Cc)
        C(von, GBN_inl, c=self.circuit.Cc_cascode)
        C(von, GBP_inl, c=self.circuit.Cc_cascode)        
        C(GBN_outl, Vss(), c=self.circuit.GBN_Cc)
        C(GBP_outr, Vss(), c=self.circuit.GBP_Cc)  
              
        C(vop, GBN_inr, c=self.circuit.Cc_cascode)
        C(vop, GBP_inr, c=self.circuit.Cc_cascode)        
        C(GBN_outr, Vss(), c=self.circuit.GBN_Cc)
        C(GBP_outl, Vss(), c=self.circuit.GBP_Cc)
        self.circuit.show()
        

        """共模反馈"""
        # mid1, mid2, negVon, negVon2 = Node(4)
        # # R(op2, mid1, r=1e9)
        # # R(mid1, on2, r=1e9)
        # (negVon2, Vss(), Vss(), on2) >> VCVS(gain = 1)
        # (mid1, Vss(), op2, negVon2) >> VCVS(gain = 0.5)
        # (CMFB1, IB200U2, mid1, vcmo) >> VCVS(gain = 1) #四个端口依次对应输出正负，输入正负

        # # R(von, mid2, r=1e9)
        # # R(mid2, vop, r=1e9)
        # (negVon, Vss(), Vss(), von) >> VCVS(gain = 1)
        # (mid2, Vss(), vop, negVon) >> VCVS(gain = 0.5)
        # (CMFB2, IB200U2, mid2, vcmo) >> VCVS(gain = 1)

        # return vop, von



